feat(plugins): add @devframes/plugin-git Git dashboard#38
Merged
Conversation
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
A publishable devframe plugin that surfaces a read-only Git dashboard (status, log, branches, diff) through type-safe RPC, with a Next.js App Router + shadcn/ui SPA. Resolves live over WebSocket in dev and from a build-time snapshot for static deploys; mountable into any host via createGitDevframe() or runnable standalone with the bundled devframe-git CLI.
Add a combined dev runner that starts the Next.js HMR server and the devframe RPC/WebSocket backend at once, wiring the client to the backend via NEXT_PUBLIC_DEVFRAME_WS. Print a ready banner from the CLI so the headless server no longer looks idle, and keep dev:client / dev:server for running a single side.
- Light/dark mode following the system preference with a manual toggle
and a no-flash inline script; theme tokens already shipped in globals.css.
- SourceTree-style commit graph in the log: git:log now returns parent
hashes (--topo-order) and the client computes lanes and draws colored
SVG edges/nodes alongside fixed-height commit rows.
- Stage / unstage / commit from the UI via gated git:stage, git:unstage,
and git:commit actions (createGitDevframe({ write: true }) or --write).
Status reports canWrite; the UI exposes per-file and bulk controls plus
a commit box only when write mode is on over a live connection.
Redesign the commit list around a SourceTree/GitLens-style graph: colored lane lines with hollow ringed nodes, left-aligned branch/tag label pills (the checked-out branch rendered as a solid current pill), per-row lane-tinted highlight bars, and a dashed "Work in Progress" row driven by the working-tree status. Branch/tag/remote/HEAD refs are parsed from the raw git ref strings. Also fixes the previously broken Storybook build by wiring the React JSX plugin needed under Vite 8's rolldown bundler.
…ls with stories The git:log snapshot baked only page one and served it for every request, so in a static deploy 'Load more' could never advance and was disabled outright. Bake the head of history (up to the 200-commit handler ceiling) as the snapshot instead, reporting hasMore: false since a static bundle has no further page — the dashboard now shows full history offline and live mode keeps paginating. Drops the now-unnecessary live-only gate on the button. Adds Storybook stories for the status, branches, and diff panel views alongside the existing log stories.
Replace the manual Load more button with an IntersectionObserver sentinel that streams the next 30-commit page as the list scrolls, and make commit rows selectable. Selecting a commit opens a details panel in the right sidebar (subject, refs, author/committer, parents, message, changed files, and the patch) backed by a new git:show RPC. The RPC bakes per-commit records for the snapshot window so static builds show details offline.
Give the dashboard an identity tied to the commit graph: the neutral grayscale primary/ring tokens become a violet accent (light and dark), surfacing in the logo chip, focus rings, selected commit, and patch hunk headers. Add a sticky app-shell top bar, slim theme-aware scrollbars for native overflow regions, and a selection color. Apply data-presentation rules across the panels: tabular-nums for every technical value (counts, ahead/behind, SHAs, +/- stats, relative times) so they stop jittering, and title attributes on truncated subjects, refs, paths, and branch names so the full value is recoverable on hover. Also drops an em dash from a status string.
Rework the dashboard into a devtools shell modeled on vite-devtools' rolldown UI: a fixed-height app that fills the viewport with no page scroll, flat panels separated by a single 1px border that doubles as a drag-to-resize handle (left sidebar and the commit-details rail persist their widths to localStorage), and each panel scrolling inside its own region. Drops the rounded card chrome, folds the branch list into the left rail under its own panel heading, and makes the Status and commit-details panels fill and scroll like the commit log already does. The patch renderer gains an inline (non-scrolling) mode so the details rail keeps a single scroll context. Storybook's decorator now frames stories in a fixed-height bordered panel to match.
67567eb to
b7b59c9
Compare
There was a problem hiding this comment.
Pull request overview
Adds @devframes/plugin-git as a new built-in devframe plugin providing a Git dashboard (RPC-backed status/log/branches/diff + optional write actions) with a standalone CLI and a bundled Next.js SPA for hosted/static usage.
Changes:
- Registers the new
plugins/gitworkspace with build/test wiring (turbo + vitest) and adds required frontend/storybook deps to pnpm catalogs. - Implements the Git RPC surface (status/log/branches/diff/show + optional stage/unstage/commit) and a CLI entry for standalone running/building.
- Adds a Next.js App Router + shadcn/ui client (components, views, Storybook stories) and corresponding build/dev scripts.
Reviewed changes
Copilot reviewed 72 out of 75 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.config.ts | Includes plugins/git in Vitest workspace projects. |
| turbo.json | Adds Turbo build pipelines for @devframes/plugin-git build + cli:build outputs. |
| tests/snapshots/tsnapi/@devframes/plugin-git/index.snapshot.js | New public API snapshot for the plugin entry. |
| tests/snapshots/tsnapi/@devframes/plugin-git/index.snapshot.d.ts | New public API type snapshot for the plugin entry. |
| pnpm-workspace.yaml | Adds catalog deps for Radix UI, Tailwind v4 stack, Storybook React/Vite, etc. |
| plugins/git/tsdown.config.ts | tsdown config for node-side entries (index, cli). |
| plugins/git/tsconfig.json | Plugin TS config with explicit include/exclude (excluding Next client output dirs). |
| plugins/git/test/git.test.ts | End-to-end RPC + snapshot dump tests for status/log/branches/diff and write actions. |
| plugins/git/test/_utils.ts | Test utilities to boot an in-process HTTP+WS server + host context. |
| plugins/git/test/_repo.ts | Test repo fixtures for deterministic git history/status/diffs. |
| plugins/git/src/rpc/index.ts | Aggregates RPC function definitions and module augmentation for typed RPC. |
| plugins/git/src/rpc/functions/unstage.ts | Implements git:unstage action (write mode only). |
| plugins/git/src/rpc/functions/status.ts | Implements git:status query and porcelain-v2 parsing. |
| plugins/git/src/rpc/functions/stage.ts | Implements git:stage action (write mode only). |
| plugins/git/src/rpc/functions/show.ts | Implements git:show query + static dump behavior for commit details. |
| plugins/git/src/rpc/functions/log.ts | Implements git:log query + static dump fallback page. |
| plugins/git/src/rpc/functions/diff.ts | Implements git:diff query with optional per-file unified patch. |
| plugins/git/src/rpc/functions/commit.ts | Implements git:commit action (write mode only) returning status + message. |
| plugins/git/src/rpc/functions/branches.ts | Implements git:branches query for local branches + upstream tracking. |
| plugins/git/src/rpc/context.ts | Per-context git configuration + memoized repo root resolution. |
| plugins/git/src/node/git.ts | Node helpers to execute git commands, parse output, and format errors. |
| plugins/git/src/index.ts | Defines createGitDevframe and exports the plugin’s public types. |
| plugins/git/src/client/tsconfig.json | Next.js client TS config for the SPA. |
| plugins/git/src/client/postcss.config.mjs | Tailwind v4 PostCSS config for the SPA. |
| plugins/git/src/client/next.config.mjs | Next export config for portable static output (relative assets + trailingSlash). |
| plugins/git/src/client/lib/utils.ts | cn() utility for class merging (clsx + tailwind-merge). |
| plugins/git/src/client/lib/refs.ts | Parses git %D refs into structured labels for the commit graph. |
| plugins/git/src/client/lib/refs.test.ts | Unit tests for parseRefs. |
| plugins/git/src/client/lib/commit-graph.ts | Computes commit graph lane layout for the log view. |
| plugins/git/src/client/components/views/status-panel-view.tsx | Status UI (staged/unstaged/untracked + optional commit UI). |
| plugins/git/src/client/components/views/status-panel-view.stories.tsx | Storybook stories for Status panel UI. |
| plugins/git/src/client/components/views/log-panel-view.tsx | Commit log UI with computed graph + infinite scroll sentinel. |
| plugins/git/src/client/components/views/log-panel-view.stories.tsx | Storybook stories for Log panel UI. |
| plugins/git/src/client/components/views/diff-panel-view.tsx | Diff list UI + patch renderer component. |
| plugins/git/src/client/components/views/diff-panel-view.stories.tsx | Storybook stories for Diff panel UI. |
| plugins/git/src/client/components/views/commit-details-view.tsx | Commit detail UI (metadata, changed files, patch when available). |
| plugins/git/src/client/components/views/commit-details-view.stories.tsx | Storybook stories for Commit details UI. |
| plugins/git/src/client/components/views/branches-panel-view.tsx | Branch list UI with upstream tracking indicators. |
| plugins/git/src/client/components/views/branches-panel-view.stories.tsx | Storybook stories for Branches panel UI. |
| plugins/git/src/client/components/use-rpc-resource.ts | Client hook for loading/refreshing RPC-backed resources. |
| plugins/git/src/client/components/ui/textarea.tsx | shadcn/ui textarea component. |
| plugins/git/src/client/components/ui/tabs.tsx | shadcn/ui tabs component (Radix). |
| plugins/git/src/client/components/ui/skeleton.tsx | shadcn/ui skeleton component. |
| plugins/git/src/client/components/ui/separator.tsx | shadcn/ui separator component (Radix). |
| plugins/git/src/client/components/ui/scroll-area.tsx | shadcn/ui scroll area component (Radix). |
| plugins/git/src/client/components/ui/card.tsx | shadcn/ui card component. |
| plugins/git/src/client/components/ui/button.tsx | shadcn/ui button component (cva + Radix Slot). |
| plugins/git/src/client/components/ui/badge.tsx | shadcn/ui badge component (cva + Radix Slot). |
| plugins/git/src/client/components/theme.ts | Theme hook syncing .dark and localStorage. |
| plugins/git/src/client/components/status-panel.tsx | Status container wiring RPC calls to Status view (including write actions). |
| plugins/git/src/client/components/rpc-provider.tsx | Connects to devframe RPC and provides client context to the app. |
| plugins/git/src/client/components/log-panel.tsx | Log container wiring pagination + status decoration into Log view. |
| plugins/git/src/client/components/diff-panel.tsx | Diff container wiring scope toggle + per-file patch fetching. |
| plugins/git/src/client/components/dashboard.tsx | Main dashboard layout (panes, branch selection, resizable rails). |
| plugins/git/src/client/components/commit-details-panel.tsx | Commit details container wiring git:show to details view. |
| plugins/git/src/client/components/branches-panel.tsx | Branches container wiring git:branches to branches view. |
| plugins/git/src/client/app/page.tsx | Next App Router page mounting the dashboard. |
| plugins/git/src/client/app/layout.tsx | Next root layout + inline theme bootstrap script. |
| plugins/git/src/client/app/globals.css | Tailwind v4 theme + utilities and base styles for the dashboard. |
| plugins/git/src/cli.ts | Standalone CLI entry using createCli(createGitDevframe()). |
| plugins/git/scripts/dev.mjs | Dev script that runs devframe backend + Next dev server concurrently. |
| plugins/git/scripts/build-spa.mjs | Copies Next export output into dist/client for packaging. |
| plugins/git/README.md | Plugin documentation (install/CLI/programmatic usage + RPC surface). |
| plugins/git/package.json | New publishable package manifest, scripts, deps, and bin entry. |
| plugins/git/LICENSE.md | Plugin license file. |
| plugins/git/bin.mjs | Bin shim that runs the compiled CLI entry. |
| plugins/git/.storybook/shims.d.ts | Storybook TS shim for CSS imports in config. |
| plugins/git/.storybook/preview.tsx | Storybook preview decorator for theme + global styles. |
| plugins/git/.storybook/main.ts | Storybook config (React+Vite) with Tailwind plugin wiring. |
| plugins/git/.gitignore | Ignores Next/build outputs for the plugin package. |
| plugins/code-server/tsconfig.json | Updates code-server plugin TS config to explicit include/exclude. |
| plugins/code-server/package.json | Adds typecheck script for the code-server plugin. |
| examples/next-runtime-snapshot/scripts/build-spa.mjs | Factors SPA copy logic into a script (ensures dist/ exists). |
| examples/next-runtime-snapshot/package.json | Uses the new build script instead of inline shell commands. |
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| }, []) | ||
|
|
||
| return <RpcContext value={state}>{children}</RpcContext> |
Comment on lines
+12
to
+23
| const GIT_ENV = { | ||
| ...process.env, | ||
| GIT_AUTHOR_NAME: 'Test User', | ||
| GIT_AUTHOR_EMAIL: 'test@example.com', | ||
| GIT_COMMITTER_NAME: 'Test User', | ||
| GIT_COMMITTER_EMAIL: 'test@example.com', | ||
| GIT_AUTHOR_DATE: '2020-01-01T00:00:00Z', | ||
| GIT_COMMITTER_DATE: '2020-01-01T00:00:00Z', | ||
| // Ignore the developer's global/system config so commits are deterministic. | ||
| GIT_CONFIG_GLOBAL: '/dev/null', | ||
| GIT_CONFIG_SYSTEM: '/dev/null', | ||
| } |
Comment on lines
+47
to
+51
| <pre className="font-mono text-xs leading-relaxed"> | ||
| {patch.split('\n').map((line, i) => ( | ||
| <div key={i} className={cn('px-3 whitespace-pre', patchLineClass(line))}>{line || ' '}</div> | ||
| ))} | ||
| </pre> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
@devframes/plugin-git(plugins/git/) — the first built-in plugin: a read-only Git dashboard you can drop into any devframe host or run standalone.It surfaces the workspace repository over type-safe RPC:
git:status— branch, upstream ahead/behind, and staged / unstaged / untracked filesgit:log— paginated commit historygit:branches— local branches with SHA, upstream tracking, and tip subjectgit:diff— per-file added/deleted counts plus a unified patch for a selected fileThe UI is a Next.js App Router + shadcn/ui SPA. Every function is a
querywithsnapshot: true, so the same bundle resolves live over WebSocket in dev and from a build-time snapshot for static deploys, and degrades cleanly to an emptyisRepo: falsestate outside a repository.Usage
Mount it into a host via devframe's adapters, or run it standalone:
createGitDevframe({ repoRoot?, basePath?, distDir?, port? })keeps the mount path adapter-resolved (/standalone,/__git/hosted).Packaging
Publish-ready alongside
@devframes/hub: tsdown compiles the node side todist/(.mjs+.d.mts), the SPA is built intodist/client/, and the tarball shipsbin.mjs+dist/only. Wired into the workspace (plugins/*glob, turbo, vitest); thetsnapipublic-API snapshot is included.This PR was created with the help of an agent.